////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2017-2018 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxipe2dlut10.cpp
/// @brief IPE2DLUT class implementation
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "camxcdmdefs.h"
#include "camxtuningdatamanager.h"
#include "parametertuningtypes.h"
#include "camxiqinterface.h"
#include "camxispiqmodule.h"
#include "camxnode.h"
#include "camxipe2dlut10.h"

CAMX_NAMESPACE_BEGIN

static const UINT32 IPE2DLUTLUTBufferSizeInDwords = (IPEMax2DLUTLUTNumEntries * sizeof(UINT32)) / RegisterWidthInBytes;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::Create
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult IPE2DLUT10::Create(
    IPEModuleCreateData* pCreateData)
{
    CamxResult result = CamxResultSuccess;

    if (NULL != pCreateData)
    {
        pCreateData->pModule = CAMX_NEW IPE2DLUT10;

        if (NULL != pCreateData->pModule)
        {
            result = pCreateData->pModule->Initialize(&pCreateData->initializationData);
            if (CamxResultSuccess != result)
            {
                CAMX_LOG_ERROR(CamxLogGroupPProc, "Module initialization failed !!");
                pCreateData->pModule->Destroy();
                pCreateData->pModule =  NULL;
            }
        }
        else
        {
            CAMX_ASSERT_ALWAYS_MESSAGE("Memory allocation failed");
            result = CamxResultENoMemory;
        }
    }
    else
    {
        result = CamxResultEInvalidPointer;
        CAMX_LOG_ERROR(CamxLogGroupPProc, "Null input pointer");
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::Initialize
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult IPE2DLUT10::Initialize(
    const ISPInputData* pInputData)
{
    CamxResult result = CamxResultSuccess;

    m_pLUTCmdBufferManager = CAMX_NEW CmdBufferManager();
    CAMX_ASSERT(NULL != m_pLUTCmdBufferManager);

    if (NULL != m_pLUTCmdBufferManager)
    {
        ResourceParams  params = { 0 };

        params.resourceSize                 = IPE2DLUTLUTBufferSizeInDwords * sizeof(UINT32);
        params.poolSize                     = (pInputData->requestQueueDepth * params.resourceSize);
        params.usageFlags.cmdBuffer         = 1;
        params.cmdParams.type               = CmdType::CDMDMI;
        params.alignment                    = CamxCommandBufferAlignmentInBytes;
        params.cmdParams.enableAddrPatching = 0;
        params.cmdParams.maxNumNestedAddrs  = 0;
        params.memFlags                     = CSLMemFlagUMDAccess;
        params.pDeviceIndices               = pInputData->pipelineIPEData.pDeviceIndex;
        params.numDevices                   = 1;

        result = m_pLUTCmdBufferManager->Initialize(&params);
        if (result != CamxResultSuccess)
        {
            CAMX_LOG_ERROR(CamxLogGroupPProc, "Unable to initilizee LUTCmdBufferManager, no memory");
        }
    }
    else
    {
        result = CamxResultENoMemory;
        CAMX_LOG_ERROR(CamxLogGroupPProc, "Unable to create CmdBufferManager, no memory");
    }

    result = AllocateCommonLibraryData();
    if (result != CamxResultSuccess)
    {
        CAMX_LOG_ERROR(CamxLogGroupPProc, "Unable to Allocate commonLibrary Data, no memory");
    }

    return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::WriteLUTtoDMI
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult IPE2DLUT10::WriteLUTtoDMI(
    const ISPInputData* pInputData)
{
    CamxResult  result        = CamxResultSuccess;
    UINT32      LUTOffset     = 0;
    CmdBuffer*  pDMICmdBuffer = pInputData->pipelineIPEData.ppIPECmdBuffer[CmdBufferDMIHeader];

    CAMX_ASSERT(NULL != pDMICmdBuffer);
    CAMX_ASSERT(NULL != m_pLUTDMICmdBuffer);

    // This offset holds CDM header of LTM LUTs, store this offset and node will patch it in top level payload
    m_offsetLUT = pDMICmdBuffer->GetResourceUsedDwords() * sizeof(UINT32);

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndexHue0 + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndexHue0] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndexHue0] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndexHue1 + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndexHue1] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndexHue1] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndexHue2 + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndexHue2] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndexHue2] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndexHue3 + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndexHue3] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndexHue3] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndexSaturation0 + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndexSaturation0] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndexSaturation0] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndexSaturation1 + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndexSaturation1] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndexSaturation1] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndexSaturation2 + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndexSaturation2] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndexSaturation2] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndexSaturation3 + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndexSaturation3] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndexSaturation3] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndexInverseHue + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndexInverseHue] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndexInverseHue] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndexInverseSaturation + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndexInverseSaturation] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndexInverseSaturation] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndex1DHue + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndex1DHue] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndex1DHue] * sizeof(UINT32));

    result = PacketBuilder::WriteDMI(pDMICmdBuffer,
                                     regIPE_IPE_0_PPS_CLC_2D_LUT_DMI_CFG,
                                     (LUT2DIndex1DSaturation + 1),
                                     m_pLUTDMICmdBuffer,
                                     LUTOffset,
                                     IPE2DLUTLUTSize[LUT2DIndex1DSaturation] * sizeof(UINT32));
    CAMX_ASSERT(CamxResultSuccess == result);

    LUTOffset += (IPE2DLUTLUTSize[LUT2DIndex1DSaturation] * sizeof(UINT32));

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::UpdateIPEInternalData
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult IPE2DLUT10::UpdateIPEInternalData(
    const ISPInputData* pInputData
    ) const
{
    CamxResult      result          = CamxResultSuccess;
    IpeIQSettings*  pIPEIQSettings  = reinterpret_cast<IpeIQSettings*>(pInputData->pipelineIPEData.pIPEIQSettings);
    if (NULL != pIPEIQSettings)
    {
        pIPEIQSettings->lut2dParameters.moduleCfg.EN = m_moduleEnable;

        // Post tuning metadata if setting is enabled
        if (NULL != pInputData->pIPETuningMetadata)
        {
            CAMX_STATIC_ASSERT(sizeof(IPER2DLUTRegCmd) <=
                               sizeof(pInputData->pIPETuningMetadata->IPE2DLUTData.LUT2DConfig));
            CAMX_STATIC_ASSERT((IPE2DLUTLUTBufferSizeInDwords * sizeof(UINT32)) <=
                               sizeof(pInputData->pIPETuningMetadata->IPEDMIData.packedLUT.LUT2D));

            if (NULL != m_p2DLUTLUTs)
            {
                Utils::Memcpy(&pInputData->pIPETuningMetadata->IPEDMIData.packedLUT.LUT2D,
                              m_p2DLUTLUTs,
                              (IPE2DLUTLUTBufferSizeInDwords * sizeof(UINT32)));
            }
            Utils::Memcpy(&pInputData->pIPETuningMetadata->IPE2DLUTData.LUT2DConfig,
                          &m_regCmd,
                          sizeof(IPER2DLUTRegCmd));
        }
    }
    else
    {
        result = CamxResultEInvalidPointer;
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::CreateCmdList
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult IPE2DLUT10::CreateCmdList(
    const ISPInputData* pInputData)
{
    CamxResult result = CamxResultSuccess;

    result = WriteLUTtoDMI(pInputData);

    if (CamxResultSuccess == result)
    {
        CmdBuffer* pCmdBuffer = pInputData->pipelineIPEData.ppIPECmdBuffer[CmdBufferPostLTM];

        CAMX_ASSERT(NULL != pCmdBuffer);
        result = PacketBuilder::WriteRegRange(pCmdBuffer,
                                              regIPE_IPE_0_PPS_CLC_2D_LUT_H_SHIFT_CFG,
                                              IPE2DLUTRegLength,
                                              reinterpret_cast<UINT32*>(&m_regCmd));

        if (CamxResultSuccess != result)
        {
            CAMX_ASSERT_ALWAYS_MESSAGE("Failed to write command buffer");
        }
    }
    else
    {
        CAMX_ASSERT_ALWAYS_MESSAGE("LUT write failed");
    }

    return result;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::ValidateDependenceParams
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult IPE2DLUT10::ValidateDependenceParams(
    const ISPInputData* pInputData
    ) const
{
    CamxResult result = CamxResultSuccess;

    /// @todo (CAMX-730) validate dependency parameters
    if ((NULL == pInputData->pipelineIPEData.ppIPECmdBuffer[CmdBufferPostLTM]) ||
        (NULL == pInputData->pipelineIPEData.ppIPECmdBuffer[CmdBufferDMIHeader]) ||
        (NULL == pInputData->pipelineIPEData.pIPEIQSettings))
    {
        CAMX_LOG_ERROR(CamxLogGroupPProc,
            "Invalid Input: pInputData %p ppIPECmdBuffer[CmdBufferDMIHeader] "
            "%p ppIPECmdBuffer[CmdBufferPostLTM] %p pIPEIQSettings %p",
            pInputData,
            pInputData->pipelineIPEData.ppIPECmdBuffer[CmdBufferDMIHeader],
            pInputData->pipelineIPEData.ppIPECmdBuffer[CmdBufferPostLTM],
            pInputData->pipelineIPEData.pIPEIQSettings);

        result = CamxResultEInvalidArg;
    }

    return result;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::CheckDependenceChange
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL IPE2DLUT10::CheckDependenceChange(
    ISPInputData* pInputData)
{
    BOOL             isChanged    = FALSE;
    ISPHALTagsData*  pHALTagsData = NULL;
    if ((NULL != pInputData))
    {
        pHALTagsData = pInputData->pHALTagsData;
    }

    if ((NULL != pInputData)                 &&
        (NULL != pInputData->pAECUpdateData) &&
        (NULL != pInputData->pAWBUpdateData) &&
        (NULL != pInputData->pHwContext)     &&
        (NULL != pHALTagsData))
    {
        if (NULL != pInputData->pOEMIQSetting)
        {
            m_moduleEnable = (static_cast<OEMIPEIQSetting*>(pInputData->pOEMIQSetting))->TDL10Enable;

            isChanged      = TRUE;
        }
        else
        {
            CAMX_ASSERT(NULL != pInputData->pTuningData);
            if (NULL != pInputData->pTuningData)
            {
                TuningDataManager* pTuningManager = pInputData->pTuningDataManager;
                CAMX_ASSERT(NULL != pTuningManager);

                // Search through the tuning data (tree), only when there
                // are changes to the tuning mode data as an optimization
                if ((TRUE == pInputData->tuningModeChanged)    &&
                    (TRUE == pTuningManager->IsValidChromatix()))
                {
                    m_pChromatix = pTuningManager->GetChromatix()->GetModule_tdl10_ipe(
                                       reinterpret_cast<TuningMode*>(&pInputData->pTuningData->TuningMode[0]),
                                       pInputData->pTuningData->noOfSelectionParameter);
                }

                CAMX_ASSERT(NULL != m_pChromatix);
                if (NULL != m_pChromatix)
                {
                    if (m_pChromatix != m_dependenceData.pChromatix)
                    {
                        CAMX_LOG_VERBOSE(CamxLogGroupPProc, "updating chromatix pointer");
                        m_dependenceData.pChromatix = m_pChromatix;
                        m_moduleEnable              = m_pChromatix->enable_section.twodlut_enable;
                        if (TRUE == m_moduleEnable)
                        {
                            isChanged = TRUE;
                        }
                    }
                }
                else
                {
                    CAMX_LOG_ERROR(CamxLogGroupISP, "Failed to get Chromatix");
                }
            }
            else
            {
                CAMX_LOG_ERROR(CamxLogGroupISP, "Tuning Pointer is NULL");
            }
        }

        // Check for manual tone map mode, if yes disable 2dLUT
        if ((TRUE                     == m_moduleEnable)                          &&
            (TonemapModeContrastCurve == pHALTagsData->tonemapCurves.tonemapMode))
        {
            m_moduleEnable = FALSE;
            isChanged      = FALSE;
        }

        if (TRUE == m_moduleEnable)
        {
            if (TRUE ==
                IQInterface::s_interpolationTable.IPETDL10TriggerUpdate(&pInputData->triggerData,
                                                                        &m_dependenceData))
            {
                isChanged = TRUE;
            }
        }
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupPProc, "Null Input Pointer");
    }

    return isChanged;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::FetchDMIBuffer
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult IPE2DLUT10::FetchDMIBuffer()
{
    PacketResource* pPacketResource = NULL;
    CamxResult      result          = CamxResultSuccess;

    CAMX_ASSERT(NULL != m_pLUTCmdBufferManager);

    // Recycle the last updated LUT DMI cmd buffer
    if (NULL != m_pLUTDMICmdBuffer)
    {
        m_pLUTCmdBufferManager->Recycle(m_pLUTDMICmdBuffer);
    }

    // fetch a fresh LUT DMI cmd buffer
    result = m_pLUTCmdBufferManager->GetBuffer(&pPacketResource);
    if (CamxResultSuccess == result)
    {
        m_pLUTDMICmdBuffer = static_cast<CmdBuffer*>(pPacketResource);
        if (m_pLUTDMICmdBuffer == NULL)
        {
            result = CamxResultEInvalidArg;
            CAMX_ASSERT_ALWAYS_MESSAGE("Invalid Input pointer");
        }
    }
    else
    {
        m_pLUTDMICmdBuffer = NULL;
        result             = CamxResultEUnableToLoad;
        CAMX_ASSERT_ALWAYS_MESSAGE("Failed to fetch DMI Buffer");
    }

    return result;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::RunCalculation
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult IPE2DLUT10::RunCalculation(
    const ISPInputData* pInputData)
{
    CAMX_UNREFERENCED_PARAM(pInputData);

    CamxResult       result = CamxResultSuccess;
    TDL10OutputData  outputData;

    result = FetchDMIBuffer();

    if (CamxResultSuccess == result)
    {
        outputData.pRegCmd = &m_regCmd;

        outputData.pD2H0LUT = reinterpret_cast<UINT32*>(m_pLUTDMICmdBuffer->BeginCommands(IPE2DLUTLUTBufferSizeInDwords));

        CAMX_ASSERT(NULL != outputData.pD2H0LUT);

        outputData.pD2H1LUT = outputData.pD2H0LUT + (IPE2DLUTLUTSize[LUT2DIndexHue0]);
        CAMX_ASSERT(NULL != outputData.pD2H1LUT);

        outputData.pD2H2LUT = outputData.pD2H1LUT + (IPE2DLUTLUTSize[LUT2DIndexHue1]);
        CAMX_ASSERT(NULL != outputData.pD2H2LUT);

        outputData.pD2H3LUT = outputData.pD2H2LUT + (IPE2DLUTLUTSize[LUT2DIndexHue2]);
        CAMX_ASSERT(NULL != outputData.pD2H3LUT);

        outputData.pD2S0LUT = outputData.pD2H3LUT + (IPE2DLUTLUTSize[LUT2DIndexHue3]);
        CAMX_ASSERT(NULL != outputData.pD2S0LUT);

        outputData.pD2S1LUT = outputData.pD2S0LUT + (IPE2DLUTLUTSize[LUT2DIndexSaturation0]);
        CAMX_ASSERT(NULL != outputData.pD2S1LUT);

        outputData.pD2S2LUT = outputData.pD2S1LUT + (IPE2DLUTLUTSize[LUT2DIndexSaturation1]);
        CAMX_ASSERT(NULL != outputData.pD2S2LUT);

        outputData.pD2S3LUT = outputData.pD2S2LUT + (IPE2DLUTLUTSize[LUT2DIndexSaturation2]);
        CAMX_ASSERT(NULL != outputData.pD2S3LUT);

        outputData.pD1IHLUT = outputData.pD2S3LUT + (IPE2DLUTLUTSize[LUT2DIndexSaturation3]);
        CAMX_ASSERT(NULL != outputData.pD1IHLUT);

        outputData.pD1ISLUT = outputData.pD1IHLUT + (IPE2DLUTLUTSize[LUT2DIndexInverseHue]);
        CAMX_ASSERT(NULL != outputData.pD1ISLUT);

        outputData.pD1HLUT = outputData.pD1ISLUT + (IPE2DLUTLUTSize[LUT2DIndexInverseSaturation]);
        CAMX_ASSERT(NULL != outputData.pD1HLUT);

        outputData.pD1SLUT = outputData.pD1HLUT + (IPE2DLUTLUTSize[LUT2DIndex1DHue]);
        CAMX_ASSERT(NULL != outputData.pD1SLUT);

        result = IQInterface::TDL10CalculateSetting(&m_dependenceData, pInputData->pOEMIQSetting, &outputData);
        if (CamxResultSuccess == result)
        {
            result = m_pLUTDMICmdBuffer->CommitCommands();

            if (NULL != pInputData->pIPETuningMetadata)
            {
                m_p2DLUTLUTs  = outputData.pD2H0LUT;
            }
        }
        else
        {
            CAMX_LOG_ERROR(CamxLogGroupISP, "TDL10 Calculation Failed %d", result);
        }
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupPProc, "Cannot get buffer from CmdBufferManager");
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::AllocateCommonLibraryData
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult IPE2DLUT10::AllocateCommonLibraryData()
{
    CamxResult result = CamxResultSuccess;

    UINT interpolationSize = (sizeof(tdl_1_0_0::tdl10_rgn_dataType) * (TDL10MaxNonLeafNode + 1));

    if (NULL == m_dependenceData.pInterpolationData)
    {
        // Alloc for tdl_1_0_0::tdl10_rgn_dataType
        m_dependenceData.pInterpolationData = CAMX_CALLOC(interpolationSize);
        if (NULL == m_dependenceData.pInterpolationData)
        {
            result = CamxResultENoMemory;
        }
    }
    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::Execute
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CamxResult IPE2DLUT10::Execute(
    ISPInputData* pInputData)
{
    CamxResult result = CamxResultSuccess;

    if (NULL != pInputData)
    {
        // Check if dependency is published and valid
        result = ValidateDependenceParams(pInputData);

        if ((CamxResultSuccess == result) && (TRUE == m_moduleEnable))
        {
            if (TRUE == CheckDependenceChange(pInputData))
            {
                result = RunCalculation(pInputData);
            }
            // Regardless of any update in dependency parameters, command buffers and IQSettings/Metadata shall be updated.
            if ((CamxResultSuccess == result) && (TRUE == m_moduleEnable))
            {
                result = CreateCmdList(pInputData);
            }

            if (CamxResultSuccess == result)
            {
                result = UpdateIPEInternalData(pInputData);
            }

            if (CamxResultSuccess != result)
            {
                CAMX_ASSERT_ALWAYS_MESSAGE("Operation failed %d", result);
            }
        }
    }
    else
    {
        result = CamxResultEInvalidArg;
        CAMX_ASSERT_ALWAYS_MESSAGE("Null Input Pointer");
    }

    return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::DeallocateCommonLibraryData
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID IPE2DLUT10::DeallocateCommonLibraryData()
{
    if (NULL != m_dependenceData.pInterpolationData)
    {
        CAMX_FREE(m_dependenceData.pInterpolationData);
        m_dependenceData.pInterpolationData = NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IPE2DLUT10::IPE2DLUT10
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IPE2DLUT10::IPE2DLUT10()
    : m_pLUTDMICmdBuffer(NULL)
{
    m_type         = ISPIQModuleType::IPE2DLUT;
    m_moduleEnable = TRUE;
    m_numLUT       = LUT2DIndexMax;
    m_cmdLength    = PacketBuilder::RequiredWriteRegRangeSizeInDwords(IPE2DLUTRegLength) * sizeof(UINT32);
    m_p2DLUTLUTs   = NULL;
    m_pChromatix   = NULL;

    CAMX_LOG_VERBOSE(CamxLogGroupPProc, "IPE Local Tone Map m_cmdLength %d ", m_cmdLength);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// IPE2DLUT10::~IPE2DLUT10
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IPE2DLUT10::~IPE2DLUT10()
{
    if (NULL != m_pLUTCmdBufferManager)
    {
        if (NULL != m_pLUTDMICmdBuffer)
        {
            m_pLUTCmdBufferManager->Recycle(m_pLUTDMICmdBuffer);
            m_pLUTDMICmdBuffer = NULL;
        }

        m_pLUTCmdBufferManager->Uninitialize();
        CAMX_DELETE m_pLUTCmdBufferManager;
        m_pLUTCmdBufferManager = NULL;
    }

    m_pChromatix = NULL;
    DeallocateCommonLibraryData();
}

CAMX_NAMESPACE_END
